#include "processmanagementdialog.h"
#include "ui_processmanagementdialog.h"
#include <QTreeWidgetItem>
#include <QPushButton>
#include <QMenu>
#include <QComboBox>
#include <algorithm>
#include "askprocessnamedialog.h"

ProcessManagementDialog::ProcessManagementDialog(QSqlDatabase &database, QWidget *parent)
    : QDialog(parent),
      ui(new Ui::ProcessManagementDialog),
      query(database)
{
    this->basicInfoMaps = new BasicInfoMaps(query);
    this->ui->setupUi(this);

    const auto &statusValues = this->basicInfoMaps->statusNameMapId.values();
    this->ui->offerStatus->setMinimum(*std::min_element(statusValues.begin(), statusValues.end()));
    this->ui->offerStatus->setMaximum(*std::max_element(statusValues.begin(), statusValues.end()));

    this->buildTree();
    this->setEditMode(false);

    connect(this->ui->buttonBox->button(QDialogButtonBox::Save), QPushButton::clicked, this, ProcessManagementDialog::saveInfoFrame);
    connect(this->ui->buttonBox->button(QDialogButtonBox::Cancel), QPushButton::clicked, this, [&](){this->setEditMode(false);this->onCurrentItemChanged(this->ui->treeWidget->currentItem(), nullptr);this->setEditMode(false);});
    connect(this->ui->buttonBox->button(QDialogButtonBox::Close), QPushButton::clicked, this, ProcessManagementDialog::done);
}

ProcessManagementDialog::~ProcessManagementDialog()
{
    delete this->basicInfoMaps;
    delete ui;
}

void ProcessManagementDialog::buildTree()
{
    QSqlQuery query(this->query);

    QMap<int, QTreeWidgetItem *> companyItems;
    for (int id : this->basicInfoMaps->idMapCompanyName.keys())
        companyItems.insert(id, new QTreeWidgetItem(this->ui->treeWidget, QStringList({this->basicInfoMaps->idMapCompanyName[id]})));

    qDebug()<<
    query.exec(QString( "select 投递进度.* from 投递进度 order by 公司ID, 步骤序号 asc "));
    while(query.next())
    {
        Info info(query, this->basicInfoMaps);
        this->infos.insert(new QTreeWidgetItem(companyItems[info.companyId], QStringList({"", this->basicInfoMaps->idMapProcessName[info.processId]})), info);
    }

    this->insertNewProcessMenu = new QMenu("插入进度", this);
    //this->insertNewProcessMenu->addAction("在上方插入进度", this, ProcessManagementDialog::insertProcess);
    //this->insertNewProcessMenu->addAction("在下方插入进度", this, ProcessManagementDialog::insertProcess);
    this->addNewProcessMenu = new QMenu("增加进度", this);
    this->addNewProcessMenu->addAction("增加进度", this, ProcessManagementDialog::insertProcess);
}

bool ProcessManagementDialog::isTopLevelTreeWidgetItem(QTreeWidgetItem *item)
{
    return this->infos.find(item) == this->infos.end();
}
void ProcessManagementDialog::saveInfoFrame()
{
    qDebug() << "saveInfoFrame";
    if (this->isTopLevelTreeWidgetItem(this->ui->treeWidget->currentItem()))
        return;

    bool oldSystemMode = this->__systemMode;
    this->__systemMode = true;

    Info &info = this->infos[this->ui->treeWidget->currentItem()];
    info.qDateTimeToPlanBeginTime(this->ui->planBeginTime->dateTime());
    info.qDateTimeToPlanEndTime(this->ui->planEndTime->dateTime());
    info.qDateTimeToInformTime(this->ui->informTime->dateTime());
    info.statusId = this->ui->offerStatus->value();
    info.remark = this->ui->remark->toPlainText();
    qDebug() << info.save(this->query);

    this->__systemMode = oldSystemMode;
    this->setEditMode(false);
}
void ProcessManagementDialog::insertProcess()
{
    qDebug() << "insertProcess";
    bool oldSystemMode = this->__systemMode;
    this->__systemMode = true;

    QSqlQuery query(this->query);
    auto iId = this->basicInfoMaps->companyNameMapId.find(this->ui->treeWidget->currentItem()->text(0));
    if (iId == this->basicInfoMaps->companyNameMapId.end())
        return;
    int companyId = *iId;

    query.exec(QString("select max(步骤序号) as result from 投递进度 where 公司ID = %1").arg(companyId));
    int newSequenceId = 1;
    if (query.next())
        newSequenceId = query.value("result").toInt() + 1;

    AskProcessNameDialog *apnd = new AskProcessNameDialog(QStringList(this->basicInfoMaps->idMapProcessName.values()), this);
    if (apnd->exec() == QDialog::Rejected)
        return;
    int newProcessId = this->basicInfoMaps->processNameMapId[apnd->result()];

    query.exec(QString("insert into 投递进度(公司ID, 进度ID, 步骤序号) values(%1, %2, %3)").arg(companyId).arg(newProcessId).arg(newSequenceId));
    Info info;
    info.companyId = companyId;
    info.sequence = newSequenceId;
    info.processId = newProcessId;
    QTreeWidgetItem *item = new QTreeWidgetItem(this->ui->treeWidget->currentItem(), QStringList({"", this->basicInfoMaps->idMapProcessName[newProcessId]}));
    this->infos.insert(item, info);
    this->ui->treeWidget->setCurrentItem(item);

    this->froze(false);
    this->clearInfoFrame();

    this->__systemMode = oldSystemMode;
    this->setEditMode(true);
}

void ProcessManagementDialog::onTreeWidgetContextMenuRequired(QPoint point)
{
    qDebug() << "onTreeWidgetContextMenuRequired";
    if (this->isTopLevelTreeWidgetItem(this->ui->treeWidget->currentItem()))
        this->addNewProcessMenu->exec(this->ui->treeWidget->mapToGlobal(point));
    else
        this->insertNewProcessMenu->exec(this->ui->treeWidget->mapToGlobal(point));
}

void ProcessManagementDialog::onCurrentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem*)
{
    qDebug() << "onCurrentItemChanged";
    bool oldSystemMode = this->__systemMode;
    this->__systemMode = true;

    auto iItem = this->infos.find(current);
    if (iItem != this->infos.end())
        this->setCurrentDisplayInfo(*iItem);
    else
        this->clearInfoFrame();
    this->froze(iItem == this->infos.end());

    this->__systemMode = oldSystemMode;
    this->setEditMode(false);
}

void ProcessManagementDialog::clearInfoFrame()
{
    qDebug() << "clearInfoFrame";
    bool oldSystemMode = this->__systemMode;
    this->__systemMode = true;

    this->ui->planBeginTime->setDateTime(QDateTime(QDate::currentDate()));
    this->ui->planEndTime->setDateTime(QDateTime(QDate::currentDate()));
    this->ui->informTime->setDateTime(QDateTime(QDate::currentDate()));
    this->ui->offerStatus->setValue(this->ui->offerStatus->minimum());
    this->ui->remark->clear();

    this->__systemMode = oldSystemMode;
    this->setEditMode(false);
}

void ProcessManagementDialog::froze(bool flag)
{
    qDebug() << "froze";
    bool oldSystemMode = this->__systemMode;
    this->__systemMode = true;

    this->ui->planBeginTime->setDisabled(flag);
    this->ui->planEndTime->setDisabled(flag);
    this->ui->informTime->setDisabled(flag);
    this->ui->offerStatus->setDisabled(flag);
    this->ui->remark->setDisabled(flag);

    this->__systemMode = oldSystemMode;
    this->setEditMode(false);
}

void ProcessManagementDialog::setCurrentDisplayInfo(const Info &info)
{
    qDebug() << "setCurrentDisplayInfo";
    bool oldSystemMode = this->__systemMode;
    this->__systemMode = true;

    this->ui->planBeginTime->setDateTime(info.planBeginTimeToQDateTime());
    this->ui->planEndTime->setDateTime(info.planEndTimeToQDateTime());
    this->ui->informTime->setDateTime(info.informTimeToQDateTime());
    this->ui->offerStatus->setValue(info.statusId);
    this->ui->remark->setPlainText(info.remark);

    this->__systemMode = oldSystemMode;
    this->setEditMode(false);
}

void ProcessManagementDialog::setEditMode(bool flag)
{
    if (this->__systemMode)
        return;
    qDebug() << "setEditMode";
    auto iInfo = this->infos.find(this->ui->treeWidget->currentItem());
    if (flag &&
            (iInfo == this->infos.end() ||
             (iInfo->planBeginTimeToQDateTime() == this->ui->planBeginTime->dateTime() &&
              iInfo->planEndTimeToQDateTime() == this->ui->planEndTime->dateTime() &&
              iInfo->informTimeToQDateTime() == this->ui->informTime->dateTime() &&
              iInfo->statusId == this->ui->offerStatus->value() &&
              iInfo->remark == this->ui->remark->toPlainText())))
        flag = false;

    this->__editMode = flag;
    this->ui->buttonBox->button(QDialogButtonBox::Save)->setEnabled(flag);
    this->ui->buttonBox->button(QDialogButtonBox::Cancel)->setVisible(flag);
    this->ui->buttonBox->button(QDialogButtonBox::Close)->setVisible(!flag);
    this->ui->treeWidget->setEnabled(!flag);
}

bool ProcessManagementDialog::isEditMode() const
{
    return this->__editMode;
}
void ProcessManagementDialog::onOfferStatusValueChanged(int value)
{
    this->ui->offerStatusLabel->setText(this->basicInfoMaps->idMapStatusName[value]);
}

ProcessManagementDialog::BasicInfoMaps::BasicInfoMaps(const QSqlQuery &query)
    : query(query)
{
    this->companyNameMapId = this->buildNameMapId("投递意向", "公司名称");
    this->processNameMapId = this->buildNameMapId("进度阶段", "进度阶段名称");
    this->statusNameMapId = this->buildNameMapId("状态", "状态名称");
    this->idMapCompanyName = this->buildIdMapName(this->companyNameMapId);
    this->idMapProcessName = this->buildIdMapName(this->processNameMapId);
    this->idMapStatusName = this->buildIdMapName(this->statusNameMapId);
}

ProcessManagementDialog::BasicInfoMaps::NameMapId ProcessManagementDialog::BasicInfoMaps::buildNameMapId(const QString &tableName, const QString &fieldName)
{
    QSqlQuery query(this->query);
    NameMapId result;
    query.exec(QString("select ID, %1 from %2 order by ID asc").arg(fieldName).arg(tableName));
    while(query.next())
    {
        int id = query.value("ID").toInt();
        QString text = query.value(fieldName).toString();
        result.insert(text, id);
    }
    return result;
}

ProcessManagementDialog::BasicInfoMaps::IdMapName ProcessManagementDialog::BasicInfoMaps::buildIdMapName(const NameMapId &nameMapId)
{
    IdMapName result;
    for (const QString &text : nameMapId.keys())
        result.insert(nameMapId[text], text);
    return result;
}

ProcessManagementDialog::Info::Info(QSqlQuery &query, BasicInfoMaps *basicInfoMaps)
    : companyId(query.value("公司ID").toInt()),
      planBeginTime(query.value("计划开始时间").toString()),
      planEndTime(query.value("计划结束时间").toString()),
      informTime(query.value("通知时间").toString()),
      sequence(query.value("步骤序号").toInt()),
      processId(query.value("进度ID").toInt()),
      statusId(query.value("状态ID").toInt()),
      remark(query.value("备注").toString()),
      basicInfoMaps(basicInfoMaps)
{
    //
}

bool ProcessManagementDialog::Info::save(const QSqlQuery &query)
{
    qDebug() <<QString(
                   "update 投递进度 "
                   "set 计划开始时间 = '%1', "
                   "计划结束时间 = '%2', "
                   "通知时间 = '%3', "
                   "状态ID = %4, "
                   "备注 = '%5' "
                   "where 公司ID = %6 and "
                   "进度ID = %7 and "
                   "步骤序号 = %8 ")
               .arg(this->planBeginTime)
               .arg(this->planEndTime)
               .arg(this->informTime)
               .arg(this->statusId)
               .arg(this->remark)
               .arg(this->companyId)
               .arg(this->processId)
               .arg(this->sequence);
    return QSqlQuery(query).exec(QString(
                   "update 投递进度 "
                   "set 计划开始时间 = '%1', "
                   "计划结束时间 = '%2', "
                   "通知时间 = '%3', "
                   "状态ID = %4, "
                   "备注 = '%5' "
                   "where 公司ID = %6 and "
                   "进度ID = %7 and  "
                   "步骤序号 = %8 ")
               .arg(this->planBeginTime)
               .arg(this->planEndTime)
               .arg(this->informTime)
               .arg(this->statusId)
               .arg(this->remark)
               .arg(this->companyId)
               .arg(this->processId)
               .arg(this->sequence)
               );
}
